#include "processctrl.h"
#include <algorithm>

ProcessCtrl::ProcessCtrl() = default;
bool ProcessCtrl::StartProcess(const std::wstring& exePath,
                               const std::vector<std::wstring>& args,
                               const std::wstring& workingDir) {
    Cleanup();
    // 构造命令行
    std::wstring fullCmd = L"\"" + exePath + L"\"";
    for (const auto& arg : args) {
        fullCmd += L" \"" + arg + L"\"";
    }
    // 可修改的缓冲区
    std::vector<wchar_t> cmdLineBuf(fullCmd.begin(),  fullCmd.end());
    cmdLineBuf.push_back(L'\0');
    // 解析工作目录
    std::wstring useWorkDir = workingDir;
    if (workingDir.empty())  {
        size_t pos = exePath.find_last_of(L"\\/");
        if (pos != std::wstring::npos)
            useWorkDir = exePath.substr(0,  pos);
    }
    const wchar_t* workDirPtr = useWorkDir.empty()  ? nullptr : useWorkDir.c_str();
    // 启动进程
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi;
    si.dwFlags  = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_SHOW;
    if (!CreateProcessW(
            exePath.c_str(),
            cmdLineBuf.data(),
            nullptr,
            nullptr,
            FALSE,
            CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
            nullptr,
            workDirPtr,
            &si,
            &pi)) {
        throw std::runtime_error("CreateProcess failed (" + std::to_string(GetLastError()) + ")");
    }
    m_processInfo = pi;
    m_bStarted = true;
    CloseHandle(pi.hThread);
    return true;
}
bool ProcessCtrl::IsRunning() const {
    if (!m_bStarted) return false;
    DWORD exitCode;
    return (GetExitCodeProcess(m_processInfo.hProcess, &exitCode) &&
            exitCode == STILL_ACTIVE);
}
bool ProcessCtrl::Terminate(unsigned exitCode) {
    if (!m_bStarted) return false;
    if (!TerminateProcess(m_processInfo.hProcess, exitCode))
        return false;
    Cleanup();
    return true;
}
bool ProcessCtrl::WaitForExit(DWORD timeoutMs) {
    if (!m_bStarted) return false;
    if (WaitForSingleObject(m_processInfo.hProcess, timeoutMs) != WAIT_OBJECT_0)
        return false;
    Cleanup();  // 等待成功后释放资源
    return true;
}
void ProcessCtrl::Cleanup() {
    if (m_bStarted) {
        CloseHandle(m_processInfo.hProcess);
        m_bStarted = false;
    }
}
